package com.proyecto.core.Utilidades;

import java.text.DecimalFormat;
import java.util.StringTokenizer;

import com.proyecto.core.modelo.excepciones.GeneralException;

public class UtilFinanciera {

	/**
	 * Genera el Monto de la cuota de un credito.
	 * @param montoPrestamo  : Monto del prestamo
	 * @param nroCuotas      : Numero de cuotas en la que desea pagar el credito.
	 * @param interesAnual   : El porcentaje de inteeres anual.
	 * @param frecuenciaPago : La frecuencia de pago de cada Cuota, ver obtenerFactorPeriodo
	 * @return               : Monto de la Cuota
	 * @throws GeneralException
	 */
	public static Double generarMontoCuota(double montoPrestamo,int nroCuotas,double interesAnual, String frecuenciaPago) throws GeneralException {
		int factorPeriodo = obtenerFactorPeriodo(frecuenciaPago);
		double interesPeriodo = calculaInteresPeriodo(factorPeriodo,interesAnual);
		try {
			double montoCuota = 0;
			if (interesPeriodo != 0) {
				//elevamos el primer numero al segundo numero
				double factor1 = Math.pow((1 + interesPeriodo), nroCuotas);
				double factor2 = (interesPeriodo * factor1) / (factor1 - 1);
				montoCuota = montoPrestamo * factor2;
			} else {
				montoCuota = montoPrestamo / nroCuotas;
			}
			return montoCuota;
		} catch (Exception e) {
			throw new GeneralException(
					"error.credito.expedientecredito.credCuota.generarCuotas.generarMontocuota");
		}

	}//EoM
	
	public static Double generarMontoCuotaUNICO(double saldoCapital,double interesPeriodo, int nroCuotas) throws GeneralException {

		try {
			double montoCuotaSinInteres = saldoCapital / nroCuotas; 
			double montoCuota = montoCuotaSinInteres + obtenerMontoInteres(montoCuotaSinInteres, interesPeriodo);
			return montoCuota;
		} catch (Exception e) {
			throw new GeneralException(
					"error.credito.expedientecredito.credCuota.generarCuotas.generarMontocuotaUNI");// TODO
		}

	}

	/**
	 * Metodo que permite Generar los montos que se van a pagar por capital e interes de un prestamo, en una determinada Cuota.
	 * @param montoPrestamo     : Monto del prestamo
	 * @param nroCuotas         : Numero de cuotas en la que desea pagar el credito.
	 * @param interesAnual      : El porcentaje de inteeres anual.
	 * @param frecuenciaPago    : La frecuencia de pago de cada Cuota, ver obtenerFactorPeriodo
	 * @param nroCuotasGenerar  : Numero de la cuota a la que se le generan los montos.
	 * @return					: El monto del Interes y del capital de un prestamo en la cuota deseada.
	 * @throws GeneralException
	 */
	
	public static Double[] generarMontoInteres_y_Capital(double montoPrestamo,int nroCuotas, double interesAnual, String frecuenciaPago, int nroCuotasGenerar) throws GeneralException{
		int factorPeriodo = obtenerFactorPeriodo(frecuenciaPago);		
		double interesPeriodo = calculaInteresPeriodo(factorPeriodo,interesAnual);
		double cuota = generarMontoCuota(montoPrestamo,nroCuotas,interesAnual,frecuenciaPago);		
		try{
			double saldoCapital = montoPrestamo;
			double interes = 0D;
			double cuotaCapital = 0D;
			for (int j = 0; j<nroCuotasGenerar;j++ ){
				interes = saldoCapital*interesPeriodo;
				cuotaCapital = cuota -interes;
				saldoCapital = saldoCapital - cuotaCapital;
			}//EoF
			return new Double[]{interes,cuotaCapital};
		}catch (Exception e) {
			throw new GeneralException("error.credito.expedientecredito.credCuota.generarCuotas.generarMontoInteres");
		}		
		
	}
	
	/**
	 * Calcula el Factor del Interes del Perido dependiendo deL factor
	 * @param factorPeriodo
	 * @param interesAnual
	 * @return
	 * @throws GeneralException
	 */
	public static Double calculaInteresPeriodo(int factorPeriodo,double interesAnual) throws GeneralException{
		try{
			return (interesAnual / (factorPeriodo*100));
		}catch (Exception e) {
			throw new GeneralException("error.credito.expedientecredito.credCuota.generarCuotas.generarInteresPeriodo");
		}
	}
	
	/**
	 * Obtiene el monto del interes el cual es el resultado del interes del periodo por el saldo a capital
	 * @param saldoCapital
	 * @param interesPeriodo
	 * @return
	 * @throws GeneralException
	 */
	public static Double obtenerMontoInteres(double saldoCapital, double interesPeriodo)throws GeneralException {
		try {
			return saldoCapital * interesPeriodo;
		} catch (Exception e) {
			throw new GeneralException(
					"error.credito.expedientecredito.credCuota.generarCuotas.generarMontoInteres");
		}
	}
	
	public static Double obtenerMontoInteresUNICO(double saldoCapital, double interesPeriodo, int nroCuotas)throws GeneralException {
		try {
			double cuota =  saldoCapital / nroCuotas;
			return cuota * interesPeriodo;
		} catch (Exception e) {
			throw new GeneralException(
					"error.credito.expedientecredito.credCuota.generarCuotas.generarMontoInteres");
		}
	}
	
	/**
	 * Calcula el interes cuando es una parte Unica.
	 * @param interesAnual
	 * @param fechaVencimientoPagos formtao AAAA/MM/DD
	 * @param fechaLiquidacion formtao AAAA/MM/DD
	 * @return
	 * @throws GeneralException
	 */
	public static Double calculaInteresPeriodoUNICO(double interesAnual,
			String fechaVencimientoPagos, String fechaLiquidacion)
			throws GeneralException {
		
		try {
			StringTokenizer fechaVenc = new StringTokenizer(fechaVencimientoPagos, "/");
			int annoVenc = Integer.parseInt(fechaVenc.nextToken());
			int mesVenc = Integer.parseInt(fechaVenc.nextToken());
			int diaVenc = Integer.parseInt(fechaVenc.nextToken());

			StringTokenizer fechaLiq = new StringTokenizer(fechaLiquidacion, "/");
			int annoLiq = Integer.parseInt(fechaLiq.nextToken());
			int mesLiq = Integer.parseInt(fechaLiq.nextToken());
			int diaLiq = Integer.parseInt(fechaLiq.nextToken());

			int diasVenGiros = (diaVenc) + (mesVenc * 30) + (annoVenc * 360);
			int diasLiqGiros = (diaLiq) + (mesLiq * 30) + (annoLiq * 360);

			double nroDias = diasVenGiros - diasLiqGiros*1;
			
			double  valor = ((interesAnual * (nroDias / 360d)) / 100d);
			return valor;
		} catch (Exception e) {
			throw new GeneralException(
					"error.credito.expedientecredito.credCuota.generarCuotas.generarInteresPeriodoUNI");// TODO
		}
	}
	
	/**
	 * Este Metodo retorna el factor de del periodo dependiendo de la Frecuencia del Pago de la cuota.
	 * @param fp :Frecuencia del Pago de la Cuota. 
	 * @return EL factor de multiplicacion dependiendo del pago de la Cuota.
	 */
	public static int obtenerFactorPeriodo(String fp){
		int factorPeriodo = 12;
		if(fp.equalsIgnoreCase("UNI")){
			factorPeriodo = 0;
		}else if (fp.equalsIgnoreCase("SEM")){//semanal
			factorPeriodo = 48;//ver si es 52
		}else if(fp.equalsIgnoreCase("QUIN")){//quincenal
			factorPeriodo = 24;//ver si es 26
		}else if(fp.equalsIgnoreCase("MEN")){
			factorPeriodo = 12;
		}else if(fp.equalsIgnoreCase("BIME")){
			factorPeriodo = 6;
		}else if (fp.equalsIgnoreCase("TRIM")){
			factorPeriodo = 4;
		}else if (fp.equalsIgnoreCase("SEMES")){
			factorPeriodo = 2;
		}else if (fp.equalsIgnoreCase("ANU")){
			factorPeriodo = 1;
		}
		return factorPeriodo;
	}
	
	

	public static String redondeaA2decimales(double valor){
		DecimalFormat df = new DecimalFormat("0.00"); 
		String s = df.format(valor);  
		return s;
	}
	
	 public static double redondear(double val, int places) {
		 long factor = (long)Math.pow(10,places);
		 val = val * factor;
		 long tmp = Math.round(val);
		 return (double)tmp / factor;
	}
	

	 public static double redondearSinIncrementar(double val, int places) {
		 long factor = (long)Math.pow(10,places);
		 val = val * factor;
		 long tmp = (long)Math.abs(val);
		 return (double)tmp / factor;
	}
}
